import datetime
import json
import redis
import bisect
import requests
from django.contrib import auth
from django.contrib.auth.models import User
from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

from ziping.bazi import bazi_by_date, bazi_by_sizhu
from yi.my_auth import my_login_required, request_data
from yi.consts import WX_MINI_AppSecret, WX_MINI_AppID, WX_CODE2SESSION_API
from .models import UserPan, UserInfo, ShenSha, FeedBack


def login_view(request):
    """
    method: POST
    api: /api/login/
    params:
        code
    """
    code = request.GET['code']
    resp = requests.get(WX_CODE2SESSION_API, params={
        'appid': WX_MINI_AppID,
        'secret': WX_MINI_AppSecret,
        'grant_type': 'authorization_code',
        'js_code': code
    })
    ans = resp.json()
    if UserInfo.objects.filter(openid=ans['openid']).exists():
        ui = UserInfo.objects.get(openid=ans['openid'])
    else:
        user = User.objects.create_user(username=f"wx-{ans['openid']}")
        user.set_password(ans['openid'])
        user.save()
        ui = UserInfo.objects.create(user=user, openid=ans['openid'])

    user = auth.authenticate(
        username=f"wx-{ans['openid']}",
        password=ans['openid'],
        backend='django.contrib.auth.backends.ModelBackend')
    auth.login(request, user, backend='django.contrib.auth.backends.ModelBackend')
    cache = redis.StrictRedis()
    cache.set(f'openid:{ui.openid}', str(ui.user.id))
    return JsonResponse({'code': 0, 'msg': '', 'data': ui.to_json()})


@csrf_exempt
@my_login_required
def edit_user_info_view(request):
    """
    method: POST
    api: /api/edit_user_info/
    """
    req_data = request_data(request)
    ui = UserInfo.objects.get(user=request.user)
    ui.nickname = req_data['nickName']
    ui.avatar = req_data['avatarUrl']
    ui.detail = json.dumps(req_data)
    ui.save()
    return JsonResponse({'code': 0, 'msg': '', 'data': ui.to_json()})



def index_view(request):
    """
    api: /
    method: GET
    """
    gender = request.GET.get('gender', 'male')
    date_type = request.GET.get('date_type')
    if date_type:
        gz_list = []
        dt_list = request.GET.getlist('dt')
        year, month, day, hour = dt_list
        mp = bazi_by_date(int(year), int(month), int(day), int(hour), 0, gender, date_type)
    else:
        dt_list = []
        gz_list = request.GET.getlist('gz')
        if gz_list:
            mp = bazi_by_sizhu(gz_list, gender)
        else:
            mp = None

    context = {
        'mp': mp and mp.to_json(),
        'gender': gender,
        'date_type': date_type,
        'dt_list': dt_list,
        'gz_list': gz_list,
    }
    return render(request, 'index.html', context)


@my_login_required
def gen_report_view(request):
    """
    method: GET
    api: /api/gen_report/
    params:
        name:
        gender:
        date_type: 可选，默认公历
        date:
        hour:
    """
    name = request.GET['name'] or '匿名'
    gender = request.GET['gender']
    date_type = request.GET.get('date_type', '阳历')
    dt = request.GET['date']
    tm = request.GET['time']
    birthday = datetime.datetime.strptime(f'{dt} {tm}', '%Y-%m-%d %H:%M')
    mp = bazi_by_date(
        birthday.year,
        birthday.month,
        birthday.day,
        birthday.hour,
        birthday.minute,
        'male' if gender == '男' else 'female',
        date_type='Solar' if date_type == '阳历' else 'Lunar'
    )
    up, _ = UserPan.objects.get_or_create(
        user=request.user,
        name=name,
        gender=gender,
        input=f'{date_type} {dt} {tm}',
    )
    up.report = json.dumps(mp.to_json())
    up.tags = json.dumps(mp.calc_tags())
    up.views += 1
    up.save()
    return JsonResponse({'code': 0, 'msg': '', 'id': up.id})


@my_login_required
def gen_report2_view(request):
    """
    method: GET
    api: /api/gen_report2/
    params:
        name:
        gender:
        year:
        month:
        day:
        hour:
    """
    name = request.GET['name'] or '匿名'
    gender = request.GET['gender']
    year = request.GET['year']
    month = request.GET['month']
    day = request.GET['day']
    hour = request.GET['hour']

    mp = bazi_by_sizhu([year, month, day, hour], gender='male' if gender == '男' else 'female')
    up, _ = UserPan.objects.get_or_create(
        user=request.user,
        name=name,
        gender=gender,
        input=' '.join([year, month, day, hour]),
    )
    up.report = json.dumps(mp.to_json())
    up.tags = json.dumps(mp.calc_tags())
    up.views += 1
    up.is_delete = False
    up.save()
    return JsonResponse({'code': 0, 'msg': '', 'id': up.id})


@my_login_required
def report_view(request, rpt_id):
    """
    method: GET
    api: /api/report/<rpt_id>/
    """
    rpt = UserPan.objects.get(id=rpt_id)
    rpt.views += 1
    rpt.save()
    return JsonResponse({
        'code': 0, 'msg': '',
        'data': rpt.to_json()
    })


@my_login_required
def dyln_view(request, rpt_id):
    """
    设置大运流年
    method: GET
    api: /api/report/<rpt_id>/dyln/
    """
    dayun = request.GET.get('dayun')
    liunian = request.GET.get('liunian')

    rpt = UserPan.objects.get(id=rpt_id)
    mp = rpt.rebuild_mp()
    if dayun:
        mp.set_dayun(dayun)
    if liunian:
        mp.set_liunian(liunian)
    return JsonResponse({
        'code': 0, 'msg': '',
        'data': mp.dayun_liunian()
    })


@my_login_required
def explanation_view(request, rpt_id):
    """
    method: GET
    api: /api/report/<rpt_id>/explanation/
    """
    rpt = UserPan.objects.get(id=rpt_id)
    return JsonResponse({
        'code': 0, 'msg': '',
        'data': rpt.explanation()
    })


@my_login_required
def reports_view(request):
    """
    method: GET
    api: /api/reports/
    """
    page = int(request.GET.get('page', 1))
    start = (page-1) * 20
    qs = UserPan.objects.filter(user=request.user, is_delete=False).order_by('-last_modified')[start:start+20]
    return JsonResponse({
        'code': 0, 'msg': '',
        'data': [{'id': p.id, 'name': p.name, 'input': p.input} for p in qs]
    })


@my_login_required
def delete_report_view(request, rpt_id):
    """
    method: GET
    api: /api/report/<rpt_id>/delete/
    """
    up = UserPan.objects.get(id=rpt_id)
    up.is_delete = True
    up.save()
    return JsonResponse({'code': 0, 'msg': ''})


def shenshas_view(request):
    """
    method: GET
    api: /api/shenshas/
    """
    qs = ShenSha.objects.all()
    return JsonResponse({
        'code': 0, 'msg': '',
        'data': [item.to_json() for item in qs]
    })


def shensha_view(request):
    """
    method: GET
    api: /api/shensha/
    """
    name = request.GET['name']
    shesha = ShenSha.objects.get(name=name)
    return JsonResponse({'code': 0, 'msg': '', 'data': shesha.to_json()})


@csrf_exempt
@my_login_required
def feedback_view(request):
    """
    method: POST
    api: /api/feedback/
    """
    req_data = request_data(request)
    content = req_data['content']
    FeedBack.objects.create(user=request.user, content=content)
    return JsonResponse({'code': 0, 'msg': ''})
